package itdep.jsf.internal;

import org.ajax4jsf.model.DataVisitor;
import org.ajax4jsf.model.Range;
import org.ajax4jsf.model.SequenceRange;
import org.richfaces.model.*;

import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
import java.io.IOException;
import java.util.List;

/**
 * @author Ivan Khalopik
 * @version $Revision: 23 $ $Date: 2010-06-19 09:36:09 +0000 (Sat, 19 Jun 2010) $
 */
public class ScrollableDataModel<T> extends ScrollableTableDataModel<T> implements Modifiable {
	private final SortableDataProvider<T> dataProvider;
	private List<SortField2> sortFields;

	public ScrollableDataModel(final SortableDataProvider<T> dataProvider) {
		this.dataProvider = dataProvider;
	}

	public SortableDataProvider<T> getDataProvider() {
		return dataProvider;
	}

	@Override
	public List<T> loadData(final int startRow, final int endRow, final SortOrder sortOrder) {
		return dataProvider.getItemsByRange(startRow, endRow, sortOrder);
	}

	@Override
	public int getRowCount() {
		return dataProvider.getRowCount();
	}

	@Override
	public Object getWrappedData() {
		throw new UnsupportedOperationException();
	}

	@Override
	public void setWrappedData(final Object data) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Object getId(final T t) {
		return t != null ? dataProvider.getKey(t) : null;
	}

	@Override
	public T getObjectById(final Object id) {
		return id != null ? dataProvider.getItemByKey(id) : null;
	}

	@Override
	public void walk(final FacesContext context, final DataVisitor visitor, final Range range, final Object argument) throws IOException {
		final SequenceRange sr = (SequenceRange) range;
		final int first = sr.getFirstRow();
		final int last = first + sr.getRows();
		final Range dataRange;
		if (sortFields != null && sortFields.size() != 0) {
			/**
			 * set properties for sort 
			 */
			SortOrder sortOrder = new SortOrder();
			sortOrder.setFields(field2ToField(sortFields, context));
			dataRange = new ScrollableTableDataRange(first, last, sortOrder);
		} else {
			dataRange = new ScrollableTableDataRange(first, last, null);
		}
		super.walk(context, visitor, dataRange, argument);
	}

	/**
	 * @param sortFields2 sort field
	 * @param context	 faces context
	 * @return array properties for sort
	 */
	public SortField[] field2ToField(List<SortField2> sortFields2, FacesContext context) {
		SortField[] sortFields = new SortField[sortFields2.size()];
		String propertyName;
		for (int i = 0; i < sortFields2.size(); i++) {
			propertyName = (String) ((ValueExpression) sortFields2.get(i).getExpression()).getValue(context.getELContext());
			if (sortFields2.get(i).getOrdering().equals(Ordering.ASCENDING) ||
					sortFields2.get(i).getOrdering().equals(Ordering.UNSORTED)) {
				sortFields[i] = new SortField(propertyName, true);
			} else {
				sortFields[i] = new SortField(propertyName, false);
			}
		}
		return sortFields;
	}


	public void modify(List<FilterField> filterFields, List<SortField2> sortFields) {
		this.sortFields = sortFields;
	}

}